package com.yn.pet.web.endpoint;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yn.common.core.redis.RedisCache;
import com.yn.pet.bus.dao.DeviceInfoDao;
import com.yn.pet.bus.entity.DeviceInfo;
import com.yn.pet.bus.entity.DeviceSim;
import com.yn.pet.bus.enums.DeviceStatusEnum;
import com.yn.pet.server.commons.model.APIResult;
import com.yn.pet.web.service.DeviceSimService;
import com.yn.pet.web.service.biz.LocationRealtimeBizService;
import com.yn.pet.protocol.basics.JTMessage;
import com.yn.pet.protocol.commons.JT808;
import com.yn.pet.protocol.t808.*;
import com.yn.pet.protocol.t808.T8100;
import com.yn.pet.protocol.t808.extend.*;
import com.yn.pet.web.model.entity.DeviceDO;
import com.yn.pet.web.model.enums.SessionKey;
import io.github.yezhihao.netmc.core.annotation.Async;
import io.github.yezhihao.netmc.core.annotation.AsyncBatch;
import io.github.yezhihao.netmc.core.annotation.Endpoint;
import io.github.yezhihao.netmc.core.annotation.Mapping;
import io.github.yezhihao.netmc.core.model.Response;
import io.github.yezhihao.netmc.session.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.yn.pet.web.service.FileService;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static com.yn.pet.protocol.commons.JT808.*;

@Endpoint
@Component
public class JT808Endpoint {

    private static final Logger log = LoggerFactory.getLogger(JT808Endpoint.class);
    @Autowired
    private FileService fileService;
    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private DeviceSimService deviceSimService;

    @Autowired
    private LocationRealtimeBizService locationRealtimeBizService;

    @Autowired
    private MessageManager messageManager;

    @Mapping(types = 终端通用应答, desc = "终端通用应答")
    public Object T0001(T0001 message, Session session) throws JsonProcessingException {
        log.info("终端通用应答:{}", objectMapper.writeValueAsString(message));
        session.response(message);
        return null;
    }

    @Mapping(types = 终端心跳, desc = "终端心跳")
    public void T0002(JTMessage message, Session session) throws JsonProcessingException {
        log.info("终端心跳:{}", objectMapper.writeValueAsString(message));
    }

    @Mapping(types = 终端注销, desc = "终端注销")
    public void T0003(JTMessage message, Session session) throws JsonProcessingException {
        log.info("终端注销:{}", objectMapper.writeValueAsString(message));
        session.invalidate();
    }

    @Mapping(types = 查询服务器时间, desc = "查询服务器时间")
    public T8004 T0004(JTMessage message, Session session) throws JsonProcessingException {
        log.info("查询服务器时间:{}", objectMapper.writeValueAsString(message));
        return new T8004(LocalDateTime.now(ZoneOffset.UTC));
    }

    @Mapping(types = 终端补传分包请求, desc = "终端补传分包请求")
    public void T8003(T8003 message, Session session) throws JsonProcessingException {
        log.info("终端补传分包请求:{}", objectMapper.writeValueAsString(message));
    }

    @Mapping(types = 终端注册, desc = "终端注册")
    public T8100 T0100(T0100 message, Session session) throws JsonProcessingException {
        log.info("终端注册:{}", objectMapper.writeValueAsString(message));
        session.register(message);
        DeviceDO device = new DeviceDO();
        device.setProtocolVersion(message.getProtocolVersion());
        device.setMobileNo(message.getClientId());
        device.setDeviceId(message.getDeviceId());
        device.setPlateNo(message.getPlateNo());
        session.setAttribute(SessionKey.Device, device);

        T8100 result = new T8100();
        result.setResponseSerialNo(message.getSerialNo());
        result.setToken(message.getDeviceId() + "," + message.getPlateNo());
        result.setResultCode(T8100.Success);
        return result;
    }

    @Mapping(types = 终端鉴权, desc = "终端鉴权")
    public T0001 T0102(T0102 message, Session session) throws JsonProcessingException {
        log.info("终端鉴权:{}", objectMapper.writeValueAsString(message));
        session.register(message);
        DeviceDO device = new DeviceDO();
        String[] token = message.getToken().split(",");
        device.setProtocolVersion(message.getProtocolVersion());
        device.setMobileNo(message.getClientId());
        device.setDeviceId(token[0]);
        if (token.length > 1)
            device.setPlateNo(token[1]);
        session.setAttribute(SessionKey.Device, device);

        T0001 result = new T0001();
        result.setResponseSerialNo(message.getSerialNo());
        result.setResponseMessageId(message.getMessageId());
        result.setResultCode(T0001.Success);
//        DeviceInfo deviceInfo = deviceInfoDao.selectList(new LambdaQueryWrapper<DeviceInfo>().eq(DeviceInfo::getImei, message.getClientId())).stream().findAny().orElse(null);
//        if (deviceInfo != null){
//            deviceInfo.setDeviceStatus(DeviceStatusEnum.MOVING.getCode());
//            deviceInfo.setStatusChangeTime(new Date());
//            deviceInfoDao.updateById(deviceInfo);
//        }


        return result;
    }

    @Mapping(types = 查询终端参数应答, desc = "查询终端参数应答")
    public void T0104(T0104 message, Session session) throws JsonProcessingException {
        log.info("查询终端参数应答:{}", objectMapper.writeValueAsString(message));
        session.response(message);
    }

    @Mapping(types = 查询终端属性应答, desc = "查询终端属性应答")
    public void T0107(T0107 message, Session session) throws JsonProcessingException {
        log.info("查询终端属性应答:{}", objectMapper.writeValueAsString(message));
        session.response(message);
    }

    @Mapping(types = 终端升级结果通知, desc = "终端升级结果通知")
    public void T0108(T0108 message, Session session) throws JsonProcessingException {
        log.info("终端升级结果通知:{}", objectMapper.writeValueAsString(message));
    }

    /**
     * 异步批量处理
     * poolSize：参考数据库CPU核心数量
     * maxElements：最大累积4000条记录处理一次
     * maxWait：最大等待时间1秒
     */
    @AsyncBatch(poolSize = 2, maxElements = 4000, maxWait = 1000)
    @Mapping(types = 位置信息汇报, desc = "位置信息汇报")
    public void T0200(List<T0200> list) throws JsonProcessingException {
        log.info("位置信息汇报:{}", objectMapper.writeValueAsString(list));
        locationRealtimeBizService.saveLocationRealtime(list);
    }

    @Mapping(types = 定位数据批量上传, desc = "定位数据批量上传")
    public void T0704(T0704 message) throws JsonProcessingException {
        log.info("定位数据批量上传:{}", objectMapper.writeValueAsString(message));
        if (message.getType() == 1){
            List<T0200> items = message.getItems();
            locationRealtimeBizService.saveLocationRealtime(items);
        }
    }

    @Mapping(types = {位置信息查询应答, 车辆控制应答}, desc = "位置信息查询应答/车辆控制应答")
    public void T0201_0500(T0201_0500 message, Session session) throws JsonProcessingException {
        log.info("位置信息查询应答:{}", objectMapper.writeValueAsString(message));
        session.response(message);
        locationRealtimeBizService.saveLocationRealtime(Collections.singletonList(message));

    }

    @Mapping(types = 事件报告, desc = "事件报告")
    public void T0301(T0301 message, Session session) throws JsonProcessingException {
        log.info("事件报告:{}", objectMapper.writeValueAsString(message));
    }

    @Mapping(types = 提问应答, desc = "提问应答")
    public void T0302(T0302 message, Session session) throws JsonProcessingException {
        log.info("提问应答:{}", objectMapper.writeValueAsString(message));
    }

    @Mapping(types = 信息点播_取消, desc = "信息点播/取消")
    public void T0303(T0303 message, Session session) throws JsonProcessingException {
        log.info("信息点播_取消:{}", objectMapper.writeValueAsString(message));
    }

    @Mapping(types = 查询区域或线路数据应答, desc = "查询区域或线路数据应答")
    public void T0608(T0608 message, Session session) throws JsonProcessingException {
        log.info("查询区域或线路数据应答:{}", objectMapper.writeValueAsString(message));
        session.response(message);
    }

    @Mapping(types = 行驶记录数据上传, desc = "行驶记录仪数据上传")
    public void T0700(T0700 message, Session session) throws JsonProcessingException {
        log.info("行驶记录数据上传:{}", objectMapper.writeValueAsString(message));
        session.response(message);
    }

    @Mapping(types = 电子运单上报, desc = "电子运单上报")
    public void T0701(JTMessage message, Session session) throws JsonProcessingException {
        log.info("电子运单上报:{}", objectMapper.writeValueAsString(message));
    }

    @Mapping(types = 驾驶员身份信息采集上报, desc = "驾驶员身份信息采集上报")
    public void T0702(T0702 message, Session session) throws JsonProcessingException {
        log.info("驾驶员身份信息采集上报:{}", objectMapper.writeValueAsString(message));
        session.response(message);
    }

    @Mapping(types = CAN总线数据上传, desc = "CAN总线数据上传")
    public void T0705(T0705 message, Session session) throws JsonProcessingException {
        log.info("CAN总线数据上传:{}", objectMapper.writeValueAsString(message));
    }

    @Mapping(types = 多媒体事件信息上传, desc = "多媒体事件信息上传")
    public void T0800(T0800 message, Session session) throws JsonProcessingException {
        log.info("多媒体事件信息上传:{}", objectMapper.writeValueAsString(message));
    }

    @Async
    @Mapping(types = 多媒体数据上传, desc = "多媒体数据上传")
    public JTMessage T0801(T0801 message, Session session) throws JsonProcessingException {
        log.info("多媒体数据上传:{}", objectMapper.writeValueAsString(message));
        if (message.getPacket() == null) {
            T0001 result = new T0001();
            result.copyBy(message);
            result.setMessageId(JT808.平台通用应答);
            result.setSerialNo(session.nextSerialNo());

            result.setResponseSerialNo(message.getSerialNo());
            result.setResponseMessageId(message.getMessageId());
            result.setResultCode(T0001.Success);
            return result;
        }
        fileService.saveMediaFile(message);
        T8800 result = new T8800();
        result.setMediaId(message.getId());
        return result;
    }

    @Mapping(types = 存储多媒体数据检索应答, desc = "存储多媒体数据检索应答")
    public void T0802(T0802 message, Session session) throws JsonProcessingException {
        log.info("存储多媒体数据检索应答:{}", objectMapper.writeValueAsString(message));
        session.response(message);
    }

    @Mapping(types = 摄像头立即拍摄命令应答, desc = "摄像头立即拍摄命令应答")
    public void T0805(T0805 message, Session session) throws JsonProcessingException {
        log.info("摄像头立即拍摄命令应答:{}", objectMapper.writeValueAsString(message));
        session.response(message);
    }

    @Mapping(types = 数据上行透传, desc = "数据上行透传")
    public void T0900(T0900 message, Session session) throws JsonProcessingException {
        log.info("数据上行透传:{}", objectMapper.writeValueAsString(message));
    }

    @Mapping(types = 数据压缩上报, desc = "数据压缩上报")
    public void T0901(T0901 message, Session session) throws JsonProcessingException {
        log.info("数据压缩上报:{}", objectMapper.writeValueAsString(message));
    }

    @Mapping(types = 终端RSA公钥, desc = "终端RSA公钥")
    public void T0A00(T0A00_8A00 message, Session session) throws JsonProcessingException {
        log.info("终端RSA公钥:{}", objectMapper.writeValueAsString(message));
        session.response(message);
    }

    @Mapping(types = 请求同步时间, desc = "请求同步时间")
    public T8109 T0109(T0109 message, Session session) throws JsonProcessingException {
        log.info("请求同步时间:{}", objectMapper.writeValueAsString(message));
        T8109 result = new T8109();
        LocalDateTime localDateTime = LocalDateTime.now();
        result.setYear(localDateTime.getYear());
        result.setMonth(localDateTime.getMonthValue());
        result.setDay(localDateTime.getDayOfMonth());
        result.setHour(localDateTime.getHour());
        result.setMinute(localDateTime.getMinute());
        result.setSecond(localDateTime.getSecond());
        return result;
    }

    @Mapping(types = 标准808协议通知, desc = "标准808协议通知")
    public Response T0808(T0808 message, Session session) throws JsonProcessingException {
        log.info("标准808协议通知:{}", objectMapper.writeValueAsString(message));
        return null;
    }

    @Mapping(types = 时区同步指令, desc = "时区同步指令")
    public void T1007(T1007 message, Session session) throws JsonProcessingException {
        log.info("时区同步指令:{}", objectMapper.writeValueAsString(message));
        System.out.println("OK");
    }

    @Mapping(types = 上传ICCID, desc = "上传ICCID")
    public void T1107(T1107 message, Session session) throws JsonProcessingException {
        log.info("上传ICCID:{}", objectMapper.writeValueAsString(message));
        String iccid = message.getIccid();
        deviceSimService.update(new UpdateWrapper<DeviceSim>().lambda().eq(DeviceSim::getPhoneNumber, message.getClientId()).set(DeviceSim::getIccid, iccid));
    }


    @Mapping(types = 短信应答透传协议, desc = "短信应答透传协议")
    public void T1300(T1300 message, Session session) throws JsonProcessingException {
        log.info("短信应答透传协议:{}", objectMapper.writeValueAsString(message));
    }

    @Mapping(types = 上传短信修改的省电模式到服务器, desc = "上传短信修改的省电模式到服务器")
    public void T0112(T0112 message, Session session) throws JsonProcessingException {
        log.info("上传短信修改的省电模式到服务器:{}", objectMapper.writeValueAsString(message));
    }
}